firmware-utiles: add *.attr for GPIO symbolic links To recognize the polarity of each GPIO, we need to expose the information from chromeos_acpi interface. BUG=chrome-os-partner:1940 TEST=(on mario, BIOS ver = G5) gpio_setup; cd /home/gpio; ls -l # complete output: (output_header[1-7] is stripped) # debug_header_0 -> /sys/class/gpio/gpio201/value # debug_header_0.attr -> /sys/bus/platform/devices/chromeos_acpi/GPIO.3/GPIO.1 # developer_switch -> /sys/class/gpio/gpio193/value # developer_switch.attr -> /sys/bus/platform/devices/chromeos_acpi/GPIO.1/GPIO.1 # recovery_button -> /sys/class/gpio/gpio230/value # recovery_button.attr -> /sys/bus/platform/devices/chromeos_acpi/GPIO.0/GPIO.1 # write_protect -> /sys/class/gpio/gpio226/value # write_protect.attr -> /sys/bus/platform/devices/chromeos_acpi/GPIO.2/GPIO.1 for X in *.attr; do echo $X - $(cat $X); done # debug_header_0.attr - 0 # developer_switch.attr - 1 # recovery_button.attr - 0 # write_protect.attr - 0 (this should be 1 in new BIOS) Change-Id: Ib42b4662c4369112a8f4fb69989d62f2d1b76590 Review URL: http://codereview.chromium.org/6324005
diff --git a/gpio_setup.cc b/gpio_setup.cc index 31fa39e..ee72847 100644 --- a/gpio_setup.cc +++ b/gpio_setup.cc
@@ -69,6 +69,7 @@ #define DEFAULT_SYMLINK_ROOT "/home/gpio" #define GPIO_SIGNAL_TYPE_EXTENSION "0" +#define GPIO_ATTRIBUTES_EXTENSION "1" #define GPIO_PIN_NUMBER_EXTENSION "2" // Debug header signal type codes are offset by 0x100, the tuple below @@ -310,7 +311,12 @@ GpioChip() { } }; -typedef std::pair<string, int> AcpiMappingEntry; +typedef struct { + string name; + int index; + int pin_number; +} AcpiMappingEntry; + typedef std::vector<AcpiMappingEntry> AcpiMapping; // Scan ACPI information about GPIO and generate a mapping. @@ -322,26 +328,32 @@ GlobResult r = glob_glob(format_string("%s/GPIO.[0-9]*", acpi_root.c_str())); AcpiMapping acpi_gpio_mapping; GlobResult::iterator i; + for (i = r.begin(); i != r.end(); i++) { + AcpiMappingEntry entry; const char *d = i->c_str(); + const char *dot_index_string = strrchr(d, '.'); int signal_type = atoi(open_read_strip( format_string("%s/GPIO.%s", d, GPIO_SIGNAL_TYPE_EXTENSION)).c_str()); - int pin_number = atoi(open_read_strip( + + assert(dot_index_string); + entry.index = atoi(dot_index_string + 1); + entry.pin_number = atoi(open_read_strip( format_string("%s/GPIO.%s", d, GPIO_PIN_NUMBER_EXTENSION)).c_str()); if (signal_type >= GPIO_SIGNAL_TYPE_MIN && signal_type <= static_cast<int>(GPIO_SIGNAL_TYPE_MAX) && GPIO_SIGNAL_TYPES[signal_type] != NULL) { - acpi_gpio_mapping.push_back(AcpiMappingEntry( - GPIO_SIGNAL_TYPES[signal_type], pin_number)); + entry.name = GPIO_SIGNAL_TYPES[signal_type]; + acpi_gpio_mapping.push_back(entry); continue; } // This is not a specific signal, could be a debug header pin. int debug_header = signal_type - GPIO_DEBUG_HEADER_RANGE[0]; if (debug_header >= 0 && debug_header < GPIO_DEBUG_HEADER_RANGE[1]) { - acpi_gpio_mapping.push_back(AcpiMappingEntry( - format_string("debug_header_%d", debug_header), pin_number)); + entry.name = format_string("debug_header_%d", debug_header); + acpi_gpio_mapping.push_back(AcpiMappingEntry(entry)); continue; } @@ -356,8 +368,23 @@ return acpi_gpio_mapping; } +void CreateSymLink(const string &source_file, const string &symlink) { + if (!os_path_exists(symlink)) { + os_symlink(source_file.c_str(), symlink.c_str()); + return; + } + + if (!os_path_islink(symlink)) + GpioSetupError("%s exists but is not a symlink", + os_path_abspath(symlink).c_str()); + if (os_readlink(symlink) != source_file) + GpioSetupError("%s points to a wrong file", + os_path_abspath(symlink).c_str()); +} + void CreateGpioSymlinks(const AcpiMapping& mappings, GpioChip &gpio, + const char *acpi_root, const char *symlink_root) { if (!os_path_exists(symlink_root)) GpioSetupError("%s does not exist", symlink_root); @@ -373,24 +400,20 @@ AcpiMapping::const_iterator i; for (i = mappings.begin(); i != mappings.end(); ++i) { - string symlink = i->first; - int pin = i->second; - gpio.EnablePin(pin); + string symlink, source_file; + gpio.EnablePin(i->pin_number); - string source_file = format_string("%s/gpio%d/value", - GPIO_ROOT, pin+gpio.base()); - if (!os_path_exists(symlink)) { - os_symlink(source_file.c_str(), symlink.c_str()); - continue; - } + symlink = i->name; + source_file = format_string("%s/gpio%d/value", GPIO_ROOT, + i->pin_number + gpio.base()); + CreateSymLink(source_file, symlink); - if (!os_path_islink(symlink)) - GpioSetupError("%s exists but is not a symlink", - os_path_abspath(symlink).c_str()); - - if (os_readlink(symlink) != source_file) - GpioSetupError("%s points to a wrong file", - os_path_abspath(symlink).c_str()); + symlink = i->name + ".attr"; + source_file = format_string("%s/GPIO.%d/GPIO.%s", + acpi_root, + i->index, + GPIO_ATTRIBUTES_EXTENSION); + CreateSymLink(source_file, symlink); } } @@ -459,6 +482,8 @@ gpioc.Attach(); CreateGpioSymlinks( ParseAcpiMappings(cmd_line_options.acpi_root), - gpioc, cmd_line_options.symlink_root.c_str()); + gpioc, + cmd_line_options.acpi_root.c_str(), + cmd_line_options.symlink_root.c_str()); return 0; }